﻿using JIESHINet.Common.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace JIESHINet.Common.Option
{
    /// <summary>
    /// Option 将appsetting的配置文件放到内存中
    /// </summary>
    public static class ConfigurableOptions
    {

        /// <summary>添加选项配置</summary>1
        /// <typeparam name="TOptions">选项类型</typeparam>
        /// <param name="services">服务集合</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddConfigurableOptions<TOptions>(this IServiceCollection services)
            where TOptions : class, IConfigurableOptions
        {
            Type optionsType = typeof(TOptions);
            string path = GetConfigurationPath(optionsType);
            // 在这里执行与配置选项相关的其他操作，但当前方法返回的是未修改的服务集合
            return services;
        }

        /// <summary>
        /// 将指定的选项类型注册到服务集合中，并配置相关的 Options 服务。
        /// </summary>
        /// <param name="services">服务集合，用于注册 Options 服务。</param>
        /// <param name="type">要注册的选项类型。</param>
        /// <returns>服务集合，以便进行链式调用。</returns>
        public static IServiceCollection AddConfigurableOptions(this IServiceCollection services, Type type)
        {
            string path = GetConfigurationPath(type);
            var config = App.Configuration.GetSection(path);

            // 定义四个 Type 变量，用于构建泛型类型
            Type iOptionsChangeTokenSource = typeof(IOptionsChangeTokenSource<>);
            Type iConfigureOptions = typeof(IConfigureOptions<>);
            Type configurationChangeTokenSource = typeof(ConfigurationChangeTokenSource<>);
            Type namedConfigureFromConfigurationOptions = typeof(NamedConfigureFromConfigurationOptions<>);

            // 将泛型类型参数设置为指定的选项类型 这四个类型最终用于注册和配置 Options 服务
            iOptionsChangeTokenSource = iOptionsChangeTokenSource.MakeGenericType(type);
            iConfigureOptions = iConfigureOptions.MakeGenericType(type);
            configurationChangeTokenSource = configurationChangeTokenSource.MakeGenericType(type);
            namedConfigureFromConfigurationOptions = namedConfigureFromConfigurationOptions.MakeGenericType(type);

            //单例依赖注册Options服务
            services.AddOptions();
            services.AddSingleton(iOptionsChangeTokenSource,
                Activator.CreateInstance(configurationChangeTokenSource, Options.DefaultName, config) ?? throw new InvalidOperationException());
            return services.AddSingleton(iConfigureOptions,
                Activator.CreateInstance(namedConfigureFromConfigurationOptions, Options.DefaultName, config) ?? throw new InvalidOperationException());
        }

        /// <summary>获取配置路径</summary>
        /// <param name="optionsType">选项类型</param>
        /// <returns></returns>
        public static string GetConfigurationPath(Type optionsType)
        {
            var endPath = new[] { "Option", "Options" };
            var configurationPath = optionsType.Name;
            foreach (var s in endPath)
            {
                if (configurationPath.EndsWith(s))
                {
                    return configurationPath[..^s.Length];
                }
            }

            return configurationPath;
        }
    }
}